// 现代 JavaScript 高阶函数和纯函数
// 作者：AI助手
// 最后更新：2024年

/**
 * 函数式编程的核心概念：
 * 1. 高阶函数：接收函数作为参数或返回函数的函数
 * 2. 纯函数：相同的输入总是产生相同的输出，没有副作用
 * 3. 不可变性：不修改输入数据，而是返回新的数据
 */

// 1. 高阶函数示例
// 1.1 接收函数作为参数的函数
function map(array, transform) {
    const result = [];
    for (const item of array) {
        result.push(transform(item));
    }
    return result;
}

// 1.2 返回函数的函数
function multiplyBy(factor) {
    return function(number) {
        return number * factor;
    };
}

// 1.3 组合函数
function compose(...functions) {
    return function(initialValue) {
        return functions.reduceRight((value, fn) => fn(value), initialValue);
    };
}

// 2. 纯函数示例
// 2.1 纯函数：相同的输入总是产生相同的输出
function add(a, b) {
    return a + b;
}

// 2.2 非纯函数：依赖外部状态
let total = 0;
function addToTotal(amount) {
    total += amount; // 修改外部状态
    return total;
}

// 2.3 纯函数：不修改输入数据
function updateUser(user, newData) {
    return { ...user, ...newData }; // 返回新对象
}

// 3. 实际应用示例
// 3.1 数据处理管道
const users = [
    { id: 1, name: '张三', age: 25, active: true },
    { id: 2, name: '李四', age: 30, active: false },
    { id: 3, name: '王五', age: 28, active: true }
];

// 纯函数组合
const isActive = user => user.active;
const isAdult = user => user.age >= 18;
const getName = user => user.name;

// 使用高阶函数处理数据
const activeAdultNames = users
    .filter(isActive)
    .filter(isAdult)
    .map(getName);

console.log('活跃的成年用户:', activeAdultNames);

// 3.2 函数组合示例
const double = x => x * 2;
const addOne = x => x + 1;
const square = x => x * x;

// 组合函数：square(addOne(double(x)))
const transform = compose(square, addOne, double);
console.log('组合函数结果:', transform(2)); // (2 * 2 + 1)² = 25

// 3.3 柯里化（Currying）
function curry(fn) {
    return function curried(...args) {
        if (args.length >= fn.length) {
            return fn.apply(this, args);
        } else {
            return function(...moreArgs) {
                return curried.apply(this, args.concat(moreArgs));
            };
        }
    };
}

// 使用柯里化
const curriedAdd = curry((a, b, c) => a + b + c);
console.log('柯里化结果:', curriedAdd(1)(2)(3)); // 6

// 4. 不可变性示例
// 4.1 修改数组（非纯函数）
function addToArray(array, item) {
    array.push(item); // 修改原数组
    return array;
}

// 4.2 不可变数组操作（纯函数）
function immutableAddToArray(array, item) {
    return [...array, item]; // 返回新数组
}

// 5. 最佳实践
// ✅ 使用纯函数进行数据处理
function calculateTotal(items) {
    return items.reduce((total, item) => total + item.price, 0);
}

// ✅ 使用高阶函数抽象通用逻辑
function withLogging(fn) {
    return function(...args) {
        console.log('调用函数:', fn.name, '参数:', args);
        const result = fn(...args);
        console.log('结果:', result);
        return result;
    };
}

// ✅ 使用函数组合提高可读性
const processUser = compose(
    user => ({ ...user, processed: true }),
    user => ({ ...user, timestamp: Date.now() })
);

// ❌ 避免副作用
// function badFunction(user) {
//     user.name = '新名字'; // 直接修改输入
//     return user;
// }

// ❌ 避免依赖外部状态
// let counter = 0;
// function increment() {
//     return ++counter; // 依赖外部状态
// }

// 6. 实际应用：购物车处理
const cart = [
    { id: 1, name: '手机', price: 5999, quantity: 1 },
    { id: 2, name: '耳机', price: 299, quantity: 2 }
];

// 纯函数处理购物车
const calculateSubtotal = item => item.price * item.quantity;
const sum = (a, b) => a + b;

const total = cart
    .map(calculateSubtotal)
    .reduce(sum, 0);

console.log('购物车总价:', total);

// 7. 使用示例
// 7.1 带日志的高阶函数
const loggedAdd = withLogging(add);
console.log('带日志的加法:', loggedAdd(2, 3));

// 7.2 用户处理管道
const user = { id: 1, name: '张三' };
const processedUser = processUser(user);
console.log('处理后的用户:', processedUser);

// 7.3 使用柯里化创建特定函数
const addFive = curriedAdd(2)(3);
console.log('柯里化特定函数:', addFive(10)); // 15 